<?php
namespace Swiftx\Component\Application;
use Swiftx\Component\Httpd\Post;
use Swiftx\Component\Httpd\Request;
use Swiftx\Component\Httpd\Session;
use Swiftx\Component\Httpd\Upload;
use Swiftx\Interfaces\Application\Config as ConfigInterface;
use Swiftx\Interfaces\Application\Server as ServerInterface;
use Swiftx\Interfaces\Httpd\Request as RequestInterface;


class Server implements ServerInterface{

    /**
     * 系统版本号
     * @var string
     */
    const VERSION = '1.0.0';

    /**
     * 是否已经引导
     * @var bool
     */
    protected $booted = false;

    /**
     * 获取应用程序版本号
     * @return string
     */
    public function version():string {
        return static::VERSION;
    }

    /**
     * 启动服务器初始化
     * @param string $root
     */
    public function boot(string $root){
        if($this->booted) return;
        $evn_file = $root.'/.evn.ini';
        if(!file_exists($evn_file)) return;
        $evn = parse_ini_file($evn_file);
        $evn['APP_ROOT'] = $root;
        $_ENV = array_replace($_ENV, $evn);
    }

    /**
     * 环境变量是否存在
     * @param string $name
     * @return bool
     */
    public function hasEvn(string $name):bool {
        return isset($_ENV[$name]);
    }

    /**
     * 读取环境变量
     * @param string $name
     * @param string $default
     * @return string
     */
    public function getEvn(string $name, string $default = null) {
        return $this->hasEvn($name)?$_ENV[$name]:$default;
    }

    /**
     * 解析真实路径
     * @param string $value
     * @return string
     * @throws \ErrorException
     */
    public function parsePath(string $value):string {
        if($value[0]=='/') return $value;
        $root = $this->getEvn('APP_ROOT');
        if($root[strlen($root)-1] != '/') $root = $root.'/';
        if(file_exists($root.$value))
            return realpath($root.$value);
        if(!mkdir($root.$value, 0777, true))
            throw new \ErrorException('目录不存在：'.$root.$value);
        return realpath($root.$value);
    }

    /**
     * 解析配置文件
     * @param string|null $file
     * @return ConfigInterface
     */
    public function parseConfig(string $file=null) : ConfigInterface{
        // 加载默认配置
        if($file === null){
            $config_dir = $this->getEvn('CONFIG_PATH','config');
            $file = $this->parsePath($config_dir.'/web.ini');
        }
        // 解析配置文件
        $config_data = parse_ini_file($file, true);
        // 构造环境解析
        $patterns = array();
        $replacements = array();
        foreach($_ENV as $key => $value){
            $patterns[] = '/\{\$'.$key.'\}/';
            $replacements[] = $value;
        }

        // 环境变量替换
        array_walk_recursive($config_data, function(&$value) use ($patterns, $replacements){
            $value = preg_replace($patterns, $replacements, $value);
        });
        // 生成配置对象
        return new Config($config_data);
    }

    /**
     * 从全局数组捕获Request对象
     * @return RequestInterface
     */
    public function captureRequest():RequestInterface{
        // 全局数据构造请求对象
        $request = new Request();
        $request->setProtocol($_SERVER['SERVER_PROTOCOL']);
        $request->setHost($_SERVER['HTTP_HOST']);
        $request->setPort((int)$_SERVER['SERVER_PORT']);
        $request->setMethod($_SERVER['REQUEST_METHOD']);
        $request->setDocument($_SERVER['DOCUMENT_URI']);
        $request->setCreateTime($_SERVER['REQUEST_TIME']);
        $request->setParams($_GET);
        // 全局数据构造POST对象
        $post = new Post();
        $post->setRawData(file_get_contents("php://input"));
        $post->setData($_POST);
        $request->setPost($post);
        // 全局数据构造SESSION
        session_start();
        $session = new Session();
        $session->setID(session_id());
        $session->mapData($_SESSION);
        $request->setSession($session);
        // 从全局数据构造Upload
        foreach($_FILES as $key => $item){
            $upload = new Upload();
            $upload->setName($item['name']);
            $upload->setType($item['type']);
            $upload->setTmpFile($item['tmp_name']);
            $upload->setError($item['error']);
            $upload->setSize($item['size']);
            $request->setUpload($key, $upload);
        }
        // 返回构造完成的请求对象
        return $request;
    }

}